from django.shortcuts import render
from django.http.response import JsonResponse
from rest_framework import viewsets
from rest_framework.views import APIView
from rest_framework import  views
from rest_framework import  status
from  rest_framework.response import  Response
from rest_framework.permissions import IsAuthenticated
from apps.login.authorizations import JWTAuthentication
import  datetime

# Create your views here.
from .serializer import *
from . import  codeRequest

import pyecharts.options as opts
from pyecharts.charts import Line
from pyecharts.globals import CurrentConfig


class IndexView(views.APIView):
	'''返回首页的数据'''
	permission_classes = [IsAuthenticated]
	authentication_classes = [JWTAuthentication]
	def get(self,request):
		products=Product.objects.count()
		apis=Api.objects.count()
		suites=Suite.objects.count()
		api_records=ApiRunRecord.objects.count()
		suite_records=SuiteRunRecord.objects.count()
		data={
			'count':
				{
					'product':products,
					'api':apis,
					'suite':suites,
					'api_records':api_records,
					'suite_records':suite_records
				}
		}
		return Response(data=data,status=status.HTTP_200_OK)


class ProductViewSets(viewsets.ModelViewSet):
	# permission_classes = [IsAuthenticated]
	# authentication_classes = [JWTAuthentication]
	queryset = Product.objects.all()
	serializer_class = ProductSerializer


class ProductView(views.APIView):
	'''产品搜索接口'''
	permission_classes = [IsAuthenticated]
	authentication_classes = [JWTAuthentication]
	def get(self,request):
		productName=request.GET.get('name')
		products=Product.objects.filter(name__contains=productName)
		serializer=ProductSerializer(products,many=True)
		return Response(data=serializer.data,status=status.HTTP_200_OK)

class HostViewSets(viewsets.ModelViewSet):
	permission_classes = [IsAuthenticated]
	authentication_classes = [JWTAuthentication]
	permission_classes = [IsAuthenticated]
	authentication_classes = [JWTAuthentication]
	queryset = Host.objects.all()
	serializer_class = HostSerializer



'''
	#根据api的模型找到所属的产品ID的信息
			records=ApiRunRecord.objects.filter(api__product_id=product_id)
'''

class HostView(views.APIView):
	'''地址搜索功能'''
	permission_classes = [IsAuthenticated]
	authentication_classes = [JWTAuthentication]
	def get(self,request):
		name=request.GET.get('name',None)
		productID=request.GET.get('productID',None)
		hosts=Host.objects.filter(name__contains=name,product_id=productID)
		serializer=HostSerializer(hosts,many=True)
		return Response(data=serializer.data,status=status.HTTP_200_OK)

class ApiViewSets(viewsets.ModelViewSet):
	permission_classes = [IsAuthenticated]
	authentication_classes = [JWTAuthentication]
	queryset = Api.objects.all()
	serializer_class = ApiSerializer


class ApiSoView(views.APIView):
	'''API的搜索'''
	def get(self,request):
		name=request.GET.get('name',None)
		productID=request.GET.get('productID',None)
		api=Api.objects.filter(name__contains=name,product_id=productID)
		serializer=ApiSerializer(api,many=True)
		return Response(data=serializer.data,status=status.HTTP_200_OK)

class RunApiView(views.APIView):
	'''发送Request的请求信息'''
	permission_classes = [IsAuthenticated]
	authentication_classes = [JWTAuthentication]
	def post(self,request,api_id):
		'''
		发送post的请求方法
		:param request:
		:param api_id: 被执行的ID的信息
		:return:
		'''
		api=Api.objects.get(pk=api_id)
		r=codeRequest.request(api=api)
		print('发送请求后的结果信息:',r.text)
		#执行执行结果的信息存储到ApiRunRecord的模型里面
		recorder=ApiRunRecord.objects.create(
			url=r.url,
			http_method=r.request.method,
			return_code=r.status_code,
			return_content=r.text,
			data=r.request.body,
			headers=r.request.headers,
			return_time=r.elapsed.total_seconds(),
			api=api
		)
		#进行序列化的处理
		serializer=ApiRunRecordSerializer(recorder)
		return Response(serializer.data,status=status.HTTP_200_OK)


class RunApiPerformance(views.APIView):
	permission_classes = [IsAuthenticated]
	authentication_classes = [JWTAuthentication]
	def post(self,request,api_id):
		api=Api.objects.get(pk=api_id)
		startTime=datetime.datetime.now()
		sum=0
		#请求的次数
		list_count=list()

		tasks=list()
		results = list()
		#失败的信息
		fails=[]
		#成功任务数
		success=[]
		codes = list()
		#请求的响应时间
		seconds = list()
		texts=[]
		for i in range(0,api.count):
			t=codeRequest.apiThread(codeRequest.performance,args=(i,i,i,api))
			tasks.append(t)
			t.start()
			print('测试中:{0}'.format(i))

		for t in tasks:
			t.join()
			if t.getResult()[0]!=200:
				fails.append(t.getResult())
			results.append(t.getResult())

		for item in fails:
			print('请求失败的信息:\n',item[2])
		endTime=datetime.datetime.now()

		for item in results:
			print('结果信息打印:\n',item)
			codes.append(item[0])
			seconds.append(item[1])
			texts.append(item[2])

		for i in range(len(codes)):
			list_count.append(i)

		#生成响应时间的可视化的趋势图
		line=Line()
		line.add_xaxis(xaxis_data=list_count)
		line.add_yaxis(
			'请求响应时间趋势图',
			seconds,
			#设置图形透明度
			areastyle_opts=opts.AreaStyleOpts(opacity=0.5, color='#00FFFF'),
			label_opts=opts.LabelOpts(is_show=False),
			# 标记点配置项
			markpoint_opts=opts.MarkPointOpts(
				data=[
					opts.MarkPointItem(type_="max", name="最大值"),
					opts.MarkPointItem(type_="min", name="最小值"),
					opts.MarkPointItem(type_="average", name="平均值")
				]),
			# 标记线配置项
			markline_opts=opts.MarkLineOpts(
				data=[opts.MarkLineItem(type_="average", name="平均值")])
		)
		line.set_global_opts(
			title_opts=opts.TitleOpts(title='API接口并发请求响应时间趋势图')
		)
		line.render('/Applications/code/Yun/storm-ui/src/assets/prod.html')


		for i in seconds:
			sum+=i
		rate=sum/len(list_count)
		# print('\n总共持续时间:\n',endTime-startTime)
		totalTime=codeRequest.calculationTime(startTime=startTime,endTime=endTime)
		if totalTime<1:
			totalTime=1

		#吞吐量的计算
		try:
			throughput=int(len(list_count)/totalTime)
		except Exception as e:
			print(e.args[0])
		codeRequest.getResult(seconds=seconds)
		errorRate=0
		if len(fails)==0:
			errorRate=0.00
		else:
			errorRate=len(fails)/len(tasks)*100
		throughput=str(throughput)+'/S'
		timeData=codeRequest.getResult(seconds=seconds)
		# print('总耗时时间:',(endTime-startTime))
		timeConsuming=(endTime-startTime)

		recorder=RunApiPermod.objects.create(
			responseTime=timeConsuming,
			throughput=throughput,
			rate=rate,
			errorRate=errorRate,
			sum=sum,
			fails=len(fails),
			maxTime=timeData['Max'],
			minTime=timeData['Min'],
			media=timeData['Median'],
			percent90=timeData['90%Line'],
			percent95=timeData['95%Line'],
			percent99=timeData['99%Line'],
			api=api
		)
		serializer=RunApiPermodSerializer(recorder)
		return Response(serializer.data,status=status.HTTP_200_OK)


class SuiteView(views.APIView):
	permission_classes = [IsAuthenticated]
	authentication_classes = [JWTAuthentication]

	def post(self,request):
		serializer=SuiteSerializer(data=request.data)
		if serializer.is_valid():
			name=request.data.get('name')
			arguments=request.data.get('arguments')
			api_list=request.data.get('api_list')
			description=request.data.get('description')
			product_id=request.data.get('product_id')
			#获取数据后开始创建测试套件
			suite=Suite.objects.create(
				name=name,
				description=description,
				product_id=product_id
			)
			#处理测试用例参数
			if arguments:
				for argument in arguments:
					SuiteArgument.objects.create(
						name=argument['name'],
						value=argument['value'],
						suite=suite
					)
			#处理api的列表信息
			if api_list:
				#进行排序,依据字典里面的index来进行排序
				api_list=sorted(api_list,key=lambda item:item['index'])
				for api in api_list:
					api_model=Api.objects.get(pk=api['id'])
					suite.api_list.add(api_model)
					api_arguments=api['arguments']
					if api_arguments:
						for api_argument in api_arguments:
							ApiArgument.objects.create(
								name=api_argument['name'],
								origin=api_argument['origin'],
								format=api_argument['format'],
								api=api_model
							)
			suite.save()
			suiteSerializer=SuiteSerializer(suite)
			return Response(suiteSerializer.data,status=status.HTTP_200_OK)
		else:
			print('全局参数返回的错误信息',serializer.errors)
			return Response(serializer.errors,status=status.HTTP_400_BAD_REQUEST)
	def put(self,request,suite_id):
		serializer=SuiteSerializer(data=request.data)
		if serializer.is_valid():
			#获取参数，然后对这些参数进行编辑前的参数校验
			name=request.data.get('name',None)
			arguments=request.data.get('arguments',None)
			api_list=request.data.get('api_list',None)
			description=request.data.get('description',None)
			product_id=request.data.get('product_id',None)

			#依据测试套件的ID信息来查询
			suite=Suite.objects.get(pk=suite_id)
			#更新名称和描述信息
			suite.name=name
			suite.description=description
			#全局参数的处理
			if arguments:
				argument_model_list=[]
				for argument in arguments:
					argument_id=argument['id']
					if argument_id:
						argument_model=SuiteArgument.objects.get(pk=argument_id)
						argument_model.name=argument['name']
						argument_model.value=argument['value']
						argument_model.save()
					else:
						#如果全部参数不存在，就直接保存，等于编辑的时候是为空的
						argument_model=SuiteArgument.objects.create(
							name=argument['name'],
							value=argument['value'],
							suite=suite
						)
					argument_model_list.append(argument_model)
				suite.arguments.set(argument_model_list)
			else:
				#如果没有参数化，就设置为空
				suite.arguments.set([])
			#处理api的参数信息
			if api_list:
				api_model_list=[]
				for api in api_list:
					api_model=Api.objects.get(pk=api['id'])
					#获取API里面的参数信息
					api_arguments=api['arguments']
					#处理API的参数
					if api_arguments:
						argument_model_list=[]
						for api_argument in api_arguments:
							argument_id=api_argument['id']
							if argument_id:
								argument_model=ApiArgument.objects.get(pk=argument_id)
								argument_model.name=api_argument['name']
								argument_model.origin=api_argument['origin']
								argument_model.format=api_argument['format']
								argument_model.save()
							else:
								argument_model=ApiArgument.objects.create(
									name=api_argument['name'],
									origin=api_argument['origin'],
									format=api_argument['format']
								)
							argument_model_list.append(argument_model)
						api_model.arguments.set(argument_model_list)
					else:
						#如果参数为空，就添加新的信息
						api_model.arguments.set([])
					#保存下API模型的参数信息
					api_model.save()
					api_model_list.append(api_model)
				suite.api_list.set(api_model_list)
			else:
				suite.api_list.set([])
			suite.save()
			return Response(data=SuiteSerializer(suite).data,status=status.HTTP_200_OK)
		else:
			print(serializer.errors)
			return Response(data=serializer.data,status=status.HTTP_400_BAD_REQUEST)
	def delete(self,request,suite_id):
		'''删除测试套件'''
		Suite.objects.get(pk=suite_id).delete()
		return Response(status=status.HTTP_204_NO_CONTENT)


class SuiteRunView(views.APIView):
	permission_classes = [IsAuthenticated]
	authentication_classes = [JWTAuthentication]

	def post(self,request,suite_id):
		#获取执行的测试套件对象
		suite=Suite.objects.get(pk=suite_id)
		#获取全部测试套件所有的参数
		suite_arguments=SuiteArgument.objects.filter(suite=suite)
		#创建测试套件执行的记录
		suite_record=SuiteRunRecord.objects.create(suite=suite)

		global_arguments={}
		#添加全局参数
		for suite_argument in suite_arguments:
			global_arguments[suite_argument.name]=suite_argument.value

		#执行测试套件里面的API以及测试动态参数的处理
		#获取测试套件里面所有的测试用例
		api_model_list=suite.api_list.all()
		for api_model in api_model_list:
			r=codeRequest.request(api=api_model,arguments=global_arguments)
			#执行的结果存储到测试套件的执行结果里面
			SuiteApiRunRecord.objects.create(
				url=r.url,
				http_method=r.request.method,
				headers=r.request.headers,
				data=r.request.body,
				return_code=r.status_code,
				return_content=r.text,
				api=api_model,
				suite_record=suite_record
			)
			#执行完第一个参数后，检查是否存在动态参数需要处理，如果需要进行处理，然后接着执行第二个API的测试用例
			api_arguments=api_model.arguments.all()
			if api_arguments:
				for api_argument in api_arguments:
					dictor_data={}
					if api_argument.origin=='HEAD':
						dictor_data=r.headers
					elif api_argument.origin=='COOKIE':
						dictor_data=r.cookies
					elif api_argument.origin=='BODY':
						dictor_data=r.json()
					argument_value=dictor(dictor_data,api_argument.format)
					global_arguments[api_argument.name]=argument_value
		serializer=SuiteRunRecordSerializer(suite_record)
		return Response(data=serializer.data,status=status.HTTP_200_OK)


class SuiteSoView(views.APIView):
	'''测试套件搜索'''
	def get(self,request):
		name=request.GET.get('name',None)
		print('name:\n',name)
		productID=request.GET.get('productID',None)
		print('productID:\n',productID)
		suite=Suite.objects.filter(name__contains=name,product_id=productID)
		serializer=SuiteSerializer(suite,many=True)
		return Response(data=serializer.data,status=status.HTTP_200_OK)

class RecordView(views.APIView):
	permission_classes = [IsAuthenticated]
	authentication_classes = [JWTAuthentication]

	#前端需要给后端传递类型以及所属的产品信息
	def get(self,request):
		#get获取的参数都是在路由里面的，如/product=product_id$type=type
		record_type=request.GET.get('type')
		product_id=request.GET.get('product')
		if record_type=='api':
			#根据api的模型找到所属的产品ID的信息
			records=ApiRunRecord.objects.filter(api__product_id=product_id)
			serializer=ApiRunRecordSerializer(records,many=True)
			print('测试用例数据:\n',serializer.data)
			return Response(data=serializer.data,status=status.HTTP_200_OK)
		#如果不是测试用例就是测试套件
		elif record_type=='suite':
			records=SuiteRunRecord.objects.filter(suite__product_id=product_id)
			serializer=SuiteRunRecordSerializer(records,many=True)
			print('测试套件数据:\n',serializer.data)
			return Response(data=serializer.data,status=status.HTTP_200_OK)
